/*
 * MainFrame.java
 *
 * Copyright(c) 2010 - Kimnach
 * See main.Main.java for full copyright notice.
 *
 * Description:
 *      Cutthroat Caverns Toolbox main frame
 *
 * Current Modules:
 *      Initiative Dealer and tracker
 *      Player death tracker
 *
 * Future Modules:
 *      Player health and prestige tracking
 *      Monster database and health tracking
 *
 */
package gui;

import exceptions.StepNotFoundException;
import gui.threads.DealAnimationThread;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import main.Main;
import player.Player;
import sequence.Step;
import sequence.Stepper;

/**
 * Main window for CC Toolbox
 * @author dkimnach
 */
public class MainFrame extends javax.swing.JFrame {

    private Main driver;
    private DealAnimationThread animator;
    private GridBagConstraints lblLayout = new GridBagConstraints();
    private GridBagConstraints txtLayout = new GridBagConstraints();
    private boolean newGame = true;
    private boolean editting = false; // are we editting a field?
    private JMenuItem miKill;
    private JMenu menuPlanB;
    private JMenuItem miTop;
    private JMenuItem miBottom;
    private javax.swing.JDialog aboutBox;
    private int counter = 0;
    private Graphics offScreenGraphicsCtx;
    private Image offScreenImage;
    private Color[] c = {Color.red, Color.yellow, Color.green, Color.magenta, Color.orange, Color.blue};
    private ArrayList<Color> colors = new ArrayList<Color>(Arrays.asList(c));

    /**
     * Constructs a new <code>MainFrame</code>
     * @param driver
     */
    public MainFrame(Main driver) {
        this.driver = driver;
        init();
        initComponents();
        updateInitLabels();
        updateSteps();
    }

    /**
     * Initializes grid layout (since NetBeans can't seem to do it the way I want it)
     */
    private void init() {
        // init grid layouts for both labels and textboxes
        lblLayout.gridx = 0;
        lblLayout.gridy = GridBagConstraints.RELATIVE;
        lblLayout.fill = java.awt.GridBagConstraints.BOTH;
        lblLayout.insets = new java.awt.Insets(5, 5, 5, 5);
        txtLayout.gridx = 1;
        txtLayout.gridy = GridBagConstraints.RELATIVE;
        txtLayout.fill = java.awt.GridBagConstraints.BOTH;
        txtLayout.insets = new java.awt.Insets(5, 5, 5, 5);
        txtLayout.weightx = 1;
        txtLayout.weighty = 1;
    }

    /**
     * Updates step labels
     */
    private void updateSteps() {
        // initial text for step labels
        try {
            Step curr = driver.getStep();
            Step next = driver.getStep(curr.next());
            Step last = driver.getLast();

            if (curr.getName().equals(Stepper.BEGIN) || curr.getName().equals(Stepper.BLANK)) {
                btnLastStep.setEnabled(false);
                miLast.setEnabled(false);
            } else {
                btnLastStep.setEnabled(true);
                miLast.setEnabled(true);
            }
            String step = curr.getName();
            if (step.equals(Stepper.PLAY) ||
                step.equals(Stepper.DMG_BEAD) ||
                step.equals(Stepper.MON_ATT) ||
                step.equals(Stepper.INIT_ATT))
            {
                if(!btnMonsterKilled.isEnabled()) {
                    btnMonsterKilled.setEnabled(true);
                    miMonsterKilled.setEnabled(true);
                }
            } else {
                if(btnMonsterKilled.isEnabled()) {
                   btnMonsterKilled.setEnabled(false);
                   miMonsterKilled.setEnabled(false);
                   btnNextStep.requestFocus();
                }
            }

            lblCurrentStep.setText(curr.getTitle());
            lblLastStep.setText(last.getTitle());
            lblNextStep.setText(next.getTitle());

        } catch (StepNotFoundException ex) {
            // shouldn't ever happen but in case it does, ignore :P
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        popPlayer = new javax.swing.JPopupMenu();
        miRemove = new javax.swing.JMenuItem();
        miChange = new javax.swing.JMenuItem();
        pnlMain = new javax.swing.JPanel();
        lblInit1 = new javax.swing.JLabel();
        txtName1 = new javax.swing.JTextField();
        lblInit2 = new javax.swing.JLabel();
        txtName2 = new javax.swing.JTextField();
        lblInit3 = new javax.swing.JLabel();
        txtName3 = new javax.swing.JTextField();
        lblInit4 = new javax.swing.JLabel();
        txtName4 = new javax.swing.JTextField();
        lblInit5 = new javax.swing.JLabel();
        txtName5 = new javax.swing.JTextField();
        lblInit6 = new javax.swing.JLabel();
        txtName6 = new javax.swing.JTextField();
        btnLastStep = new javax.swing.JButton();
        btnNextStep = new javax.swing.JButton();
        btnMonsterKilled = new javax.swing.JButton();
        lblLastStep = new javax.swing.JLabel();
        lblNextStep = new javax.swing.JLabel();
        lblCurrentStep = new javax.swing.JLabel();
        menuMain = new javax.swing.JMenuBar();
        menuFile = new javax.swing.JMenu();
        miExit = new javax.swing.JMenuItem();
        menuGame = new javax.swing.JMenu();
        miNew = new javax.swing.JMenuItem();
        miRestart = new javax.swing.JMenuItem();
        miAdd = new javax.swing.JMenuItem();
        miNext = new javax.swing.JMenuItem();
        miLast = new javax.swing.JMenuItem();
        miMonsterKilled = new javax.swing.JMenuItem();
        miDeal = new javax.swing.JMenuItem();
        menuHelp = new javax.swing.JMenu();
        miAbout = new javax.swing.JMenuItem();

        popPlayer.setLabel("");
        popPlayer.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
            public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
            }
            public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
                popPlayerPopupMenuWillBecomeInvisible(evt);
            }
            public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
                popPlayerPopupMenuWillBecomeVisible(evt);
            }
        });

        miRemove.setText("Remove Player");
        miRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miRemoveActionPerformed(evt);
            }
        });
        popPlayer.add(miRemove);

        miChange.setText("Rename Player");
        miChange.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miChangeActionPerformed(evt);
            }
        });
        popPlayer.add(miChange);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("CC Toolbox"); // NOI18N
        addWindowStateListener(new java.awt.event.WindowStateListener() {
            public void windowStateChanged(java.awt.event.WindowEvent evt) {
                formWindowStateChanged(evt);
            }
        });
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });

        pnlMain.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        pnlMain.setLayout(new java.awt.GridBagLayout());

        lblInit1.setFont(lblInit1.getFont().deriveFont((lblInit1.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit1.getFont().getSize()+24));
        lblInit1.setText("1:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit1, gridBagConstraints);

        txtName1.setBackground(java.awt.Color.red);
        txtName1.setEditable(false);
        txtName1.setFont(txtName1.getFont().deriveFont((txtName1.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName1.getFont().getSize()+24));
        txtName1.setForeground(java.awt.Color.black);
        txtName1.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName1.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName1, gridBagConstraints);
        txtName1.getAccessibleContext().setAccessibleName("txtName1");

        lblInit2.setFont(lblInit2.getFont().deriveFont((lblInit2.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit2.getFont().getSize()+24));
        lblInit2.setText("2:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit2, gridBagConstraints);

        txtName2.setBackground(java.awt.Color.yellow);
        txtName2.setEditable(false);
        txtName2.setFont(txtName2.getFont().deriveFont((txtName2.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName2.getFont().getSize()+24));
        txtName2.setForeground(java.awt.Color.black);
        txtName2.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName2.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName2.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName2, gridBagConstraints);
        txtName2.getAccessibleContext().setAccessibleName("txtName2");

        lblInit3.setFont(lblInit3.getFont().deriveFont((lblInit3.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit3.getFont().getSize()+24));
        lblInit3.setText("3:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit3, gridBagConstraints);

        txtName3.setBackground(java.awt.Color.blue);
        txtName3.setEditable(false);
        txtName3.setFont(txtName3.getFont().deriveFont((txtName3.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName3.getFont().getSize()+24));
        txtName3.setForeground(java.awt.Color.black);
        txtName3.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName3.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName3.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName3.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName3, gridBagConstraints);
        txtName3.getAccessibleContext().setAccessibleName("txtName3");

        lblInit4.setFont(lblInit4.getFont().deriveFont((lblInit4.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit4.getFont().getSize()+24));
        lblInit4.setText("4:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit4, gridBagConstraints);

        txtName4.setBackground(java.awt.Color.green);
        txtName4.setEditable(false);
        txtName4.setFont(txtName4.getFont().deriveFont((txtName4.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName4.getFont().getSize()+24));
        txtName4.setForeground(java.awt.Color.black);
        txtName4.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName4.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName4.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName4.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName4, gridBagConstraints);
        txtName4.getAccessibleContext().setAccessibleName("txtName4");

        lblInit5.setFont(lblInit5.getFont().deriveFont((lblInit5.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit5.getFont().getSize()+24));
        lblInit5.setText("5:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit5, gridBagConstraints);

        txtName5.setBackground(java.awt.Color.magenta);
        txtName5.setEditable(false);
        txtName5.setFont(txtName5.getFont().deriveFont((txtName5.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName5.getFont().getSize()+24));
        txtName5.setForeground(java.awt.Color.black);
        txtName5.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName5.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName5.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName5.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName5, gridBagConstraints);
        txtName5.getAccessibleContext().setAccessibleName("txtName5");

        lblInit6.setFont(lblInit6.getFont().deriveFont((lblInit6.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, lblInit6.getFont().getSize()+24));
        lblInit6.setText("6:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(lblInit6, gridBagConstraints);

        txtName6.setBackground(java.awt.Color.orange);
        txtName6.setEditable(false);
        txtName6.setFont(txtName6.getFont().deriveFont((txtName6.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, txtName6.getFont().getSize()+24));
        txtName6.setForeground(java.awt.Color.black);
        txtName6.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        txtName6.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txtPlayerMouseClicked(evt);
            }
        });
        txtName6.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtPlayerFocusLost(evt);
            }
        });
        txtName6.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPlayerKeyPressed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlMain.add(txtName6, gridBagConstraints);

        btnLastStep.setFont(btnLastStep.getFont().deriveFont(btnLastStep.getFont().getStyle() | java.awt.Font.BOLD, 24));
        btnLastStep.setText("<");
        btnLastStep.setEnabled(false);
        btnLastStep.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnLastStepActionPerformed(evt);
            }
        });

        btnNextStep.setFont(btnNextStep.getFont().deriveFont(btnNextStep.getFont().getStyle() | java.awt.Font.BOLD, 24));
        btnNextStep.setText(">");
        btnNextStep.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNextStepActionPerformed(evt);
            }
        });

        btnMonsterKilled.setFont(btnMonsterKilled.getFont().deriveFont((float)14));
        btnMonsterKilled.setText("Monster Killed");
        btnMonsterKilled.setEnabled(false);
        btnMonsterKilled.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnMonsterKilledActionPerformed(evt);
            }
        });

        lblLastStep.setFont(lblLastStep.getFont().deriveFont(lblLastStep.getFont().getStyle() | java.awt.Font.BOLD, 16));
        lblLastStep.setText("Last Step");
        lblLastStep.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        lblLastStep.setEnabled(false);

        lblNextStep.setFont(lblNextStep.getFont().deriveFont(lblNextStep.getFont().getStyle() | java.awt.Font.BOLD, 16));
        lblNextStep.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblNextStep.setText("Next Step");
        lblNextStep.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        lblNextStep.setEnabled(false);

        lblCurrentStep.setFont(lblCurrentStep.getFont().deriveFont(lblCurrentStep.getFont().getStyle() | java.awt.Font.BOLD, 28));
        lblCurrentStep.setForeground(java.awt.SystemColor.activeCaption);
        lblCurrentStep.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblCurrentStep.setText("Current Step");
        lblCurrentStep.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));

        menuFile.setText("File");

        miExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.event.InputEvent.ALT_MASK));
        miExit.setText("Exit");
        miExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miExitActionPerformed(evt);
            }
        });
        menuFile.add(miExit);

        menuMain.add(menuFile);

        menuGame.setText("Game");

        miNew.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.ALT_MASK));
        miNew.setText("New");
        miNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miNewActionPerformed(evt);
            }
        });
        menuGame.add(miNew);

        miRestart.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.ALT_MASK));
        miRestart.setText("Restart");
        miRestart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miRestartActionPerformed(evt);
            }
        });
        menuGame.add(miRestart);

        miAdd.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.ALT_MASK));
        miAdd.setText("Add Player");
        miAdd.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miAddActionPerformed(evt);
            }
        });
        menuGame.add(miAdd);

        miNext.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_SPACE, 0));
        miNext.setText("Next Step");
        miNext.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miNextActionPerformed(evt);
            }
        });
        menuGame.add(miNext);

        miLast.setText("Go Back a Step");
        miLast.setEnabled(false);
        miLast.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miLastActionPerformed(evt);
            }
        });
        menuGame.add(miLast);

        miMonsterKilled.setText("Kill Monster");
        miMonsterKilled.setEnabled(false);
        miMonsterKilled.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miMonsterKilledActionPerformed(evt);
            }
        });
        menuGame.add(miMonsterKilled);

        miDeal.setText("Deal Initiatives (manually)");
        miDeal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miDealActionPerformed(evt);
            }
        });
        menuGame.add(miDeal);

        menuMain.add(menuGame);

        menuHelp.setText("Help");

        miAbout.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.ALT_MASK));
        miAbout.setText("About...");
        miAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                miAboutActionPerformed(evt);
            }
        });
        menuHelp.add(miAbout);

        menuMain.add(menuHelp);

        setJMenuBar(menuMain);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pnlMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 606, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(btnLastStep, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblCurrentStep, javax.swing.GroupLayout.DEFAULT_SIZE, 443, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnNextStep, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(lblLastStep, javax.swing.GroupLayout.DEFAULT_SIZE, 236, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnMonsterKilled, javax.swing.GroupLayout.DEFAULT_SIZE, 109, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblNextStep, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(btnLastStep, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnNextStep, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(lblCurrentStep))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(btnMonsterKilled)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(lblLastStep)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 4, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(lblNextStep)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 4, Short.MAX_VALUE)))
                .addGap(18, 18, 18)
                .addComponent(pnlMain, javax.swing.GroupLayout.DEFAULT_SIZE, 371, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void popPlayerPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_popPlayerPopupMenuWillBecomeVisible
        try {
            JTextField field = ((JTextField) ((JPopupMenu) evt.getSource()).getInvoker());
            int to = 0;
            int from = 0;

            if (field.equals(txtName1)) {
                from = 0;

            } else if (field.equals(txtName2)) {
                from = 1;

            } else if (field.equals(txtName3)) {
                from = 2;

            } else if (field.equals(txtName4)) {
                from = 3;

            } else if (field.equals(txtName5)) {
                from = 4;

            } else if (field.equals(txtName6)) {
                from = 5;

            } else {
                showDiag("Congratulations, you have clicked a non-existant button for this context menu. \nEmail me at cc.toolbox@gmail.com and tell me how you did it");
            }

            if (!newGame && field.isEnabled()) {
                showContextMenu(field, from, to);
            } else {
                if (miKill != null) { popPlayer.remove(miKill); }
                if (miBottom != null) { popPlayer.remove(miBottom); }
                if (miTop != null) { popPlayer.remove(miTop); }
                if (menuPlanB != null) { popPlayer.remove(menuPlanB); }
            }
        } catch (Exception e) {
            e.printStackTrace();
            //showDiag(e.toString());
        }
    }//GEN-LAST:event_popPlayerPopupMenuWillBecomeVisible

    private void txtPlayerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_txtPlayerMouseClicked
        JTextField field = ((JTextField) evt.getSource());
        if (newGame) {
            setEditable(field);
        }
    }//GEN-LAST:event_txtPlayerMouseClicked

    private void txtPlayerFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerFocusLost
        JTextField field = ((JTextField) evt.getSource());
        setNonEditable(field);
    }//GEN-LAST:event_txtPlayerFocusLost

    private void txtPlayerKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPlayerKeyPressed
        if (evt.getKeyCode() == KeyEvent.VK_ENTER || evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
            JTextField field = ((JTextField) evt.getSource());
            setNonEditable(field);
        }
    }//GEN-LAST:event_txtPlayerKeyPressed

    private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
        System.out.println("Key pressed on form! " + KeyEvent.getKeyText(evt.getKeyCode()));
        if (evt.getKeyCode() == KeyEvent.VK_SPACE && !editting) {
            // deal();
            nextStep();
        }
    }//GEN-LAST:event_formKeyPressed

    private void miExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miExitActionPerformed
        System.exit(0);
    }//GEN-LAST:event_miExitActionPerformed

    private void miNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miNewActionPerformed
        String title = "Confirm New Game";
        String msg = "This will clear all names. \nAre you sure?";
        clear(title, msg);
    }//GEN-LAST:event_miNewActionPerformed

    private void popPlayerPopupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_popPlayerPopupMenuWillBecomeInvisible
    }//GEN-LAST:event_popPlayerPopupMenuWillBecomeInvisible

    private void miAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miAboutActionPerformed
        if (aboutBox == null) {
            JFrame mainFrame = this;
            aboutBox = new AboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        aboutBox.setVisible(true);

    }//GEN-LAST:event_miAboutActionPerformed

    private void miAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miAddActionPerformed

        if (newGame) {
            addPlayer();

        } else {
            if (confirmDiag("Confirm Add Player", "This will reset the initiative counter. Confirm?") == JOptionPane.OK_OPTION) {
                addPlayer();
                updateSteps();
            }
        }
    }//GEN-LAST:event_miAddActionPerformed

    private void miRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miRemoveActionPerformed
        JTextField field = ((JTextField) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker());

        if (newGame) {
            removePlayer(field);
        } else {
            if (confirmDiag("Confirm Remove Player", "This will reset the initiative counter. Confirm?") == JOptionPane.OK_OPTION) {
                removePlayer(field);
                update();
                updateInitLabels();
                updateSteps();
                setFont();
            }
        }
    }//GEN-LAST:event_miRemoveActionPerformed

    private void miDealActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miDealActionPerformed
        if (!editting) {
            deal();
        }
    }//GEN-LAST:event_miDealActionPerformed

    private void miChangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miChangeActionPerformed
        JTextField field = ((JTextField) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker());

        setEditable(field);
}//GEN-LAST:event_miChangeActionPerformed

    private void formWindowStateChanged(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowStateChanged

        setFont();
}//GEN-LAST:event_formWindowStateChanged

    private void miRestartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miRestartActionPerformed
        restart();
    }//GEN-LAST:event_miRestartActionPerformed

    private void btnMonsterKilledActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMonsterKilledActionPerformed
        monsterDies();
    }//GEN-LAST:event_btnMonsterKilledActionPerformed

    private void btnNextStepActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNextStepActionPerformed
        if (!editting) {
            nextStep();
        }
    }//GEN-LAST:event_btnNextStepActionPerformed

    private void btnLastStepActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLastStepActionPerformed
        backStep();
    }//GEN-LAST:event_btnLastStepActionPerformed

    private void miNextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miNextActionPerformed
        if (!editting) {
            nextStep();
        }
    }//GEN-LAST:event_miNextActionPerformed

    private void miMonsterKilledActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miMonsterKilledActionPerformed
        monsterDies();
        btnNextStep.requestFocus();
    }//GEN-LAST:event_miMonsterKilledActionPerformed

    private void miLastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_miLastActionPerformed
        backStep();
    }//GEN-LAST:event_miLastActionPerformed

    private void miKillActionPerformed(java.awt.event.ActionEvent evt) {

        JTextField field = ((JTextField) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker());

        //field.setEnabled(!field.isEnabled());

        if (field.equals(txtName1)) {
            killPlayer(0);

        } else if (field.equals(txtName2)) {
            killPlayer(1);

        } else if (field.equals(txtName3)) {
            killPlayer(2);

        } else if (field.equals(txtName4)) {
            killPlayer(3);

        } else if (field.equals(txtName5)) {
            killPlayer(4);

        } else if (field.equals(txtName6)) {
            killPlayer(5);

        }
        update();
    }

    private void miTopActionPerformed(ActionEvent evt) {
        // player that was clicked
        JTextField field = ((JTextField) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker());

        if (field.equals(txtName1)) {
            moveToTop(0);

        } else if (field.equals(txtName2)) {
            moveToTop(1);

        } else if (field.equals(txtName3)) {
            moveToTop(2);

        } else if (field.equals(txtName4)) {
            moveToTop(3);

        } else if (field.equals(txtName5)) {
            moveToTop(4);

        } else if (field.equals(txtName6)) {
            moveToTop(5);
            
        }
        update();
    }

    private void miBottomActionPerformed(ActionEvent evt) {
        // player that was clicked
        JTextField field = ((JTextField) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker());

        if (field.equals(txtName1)) {
            moveToBottom(0);

        } else if (field.equals(txtName2)) {
            moveToBottom(1);

        } else if (field.equals(txtName3)) {
            moveToBottom(2);

        } else if (field.equals(txtName4)) {
            moveToBottom(3);

        } else if (field.equals(txtName5)) {
            moveToBottom(4);

        } else if (field.equals(txtName6)) {
            moveToBottom(5);
            
        }
        update();
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnLastStep;
    private javax.swing.JButton btnMonsterKilled;
    private javax.swing.JButton btnNextStep;
    private javax.swing.JLabel lblCurrentStep;
    private javax.swing.JLabel lblInit1;
    private javax.swing.JLabel lblInit2;
    private javax.swing.JLabel lblInit3;
    private javax.swing.JLabel lblInit4;
    private javax.swing.JLabel lblInit5;
    private javax.swing.JLabel lblInit6;
    private javax.swing.JLabel lblLastStep;
    private javax.swing.JLabel lblNextStep;
    private javax.swing.JMenu menuFile;
    private javax.swing.JMenu menuGame;
    private javax.swing.JMenu menuHelp;
    private javax.swing.JMenuBar menuMain;
    private javax.swing.JMenuItem miAbout;
    private javax.swing.JMenuItem miAdd;
    private javax.swing.JMenuItem miChange;
    private javax.swing.JMenuItem miDeal;
    private javax.swing.JMenuItem miExit;
    private javax.swing.JMenuItem miLast;
    private javax.swing.JMenuItem miMonsterKilled;
    private javax.swing.JMenuItem miNew;
    private javax.swing.JMenuItem miNext;
    private javax.swing.JMenuItem miRemove;
    private javax.swing.JMenuItem miRestart;
    private javax.swing.JPanel pnlMain;
    private javax.swing.JPopupMenu popPlayer;
    private javax.swing.JTextField txtName1;
    private javax.swing.JTextField txtName2;
    private javax.swing.JTextField txtName3;
    private javax.swing.JTextField txtName4;
    private javax.swing.JTextField txtName5;
    private javax.swing.JTextField txtName6;
    // End of variables declaration//GEN-END:variables

    private void showContextMenu(final JTextField field, final int from, final int to) {
        // Plan 'B' menu items
        JMenuItem miP1 = new JMenuItem();
        JMenuItem miP2 = new JMenuItem();
        JMenuItem miP3 = new JMenuItem();
        JMenuItem miP4 = new JMenuItem();
        JMenuItem miP5 = new JMenuItem();
        JMenuItem miP6 = new JMenuItem();

        if (popPlayer.getComponentIndex(miKill) == -1) {
            miKill = new JMenuItem();
            miKill.setText("Kill");
            miKill.addActionListener(new java.awt.event.ActionListener() {

                @Override
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    miKillActionPerformed(evt);
                }
            });
            if (field.isEnabled()) {
                popPlayer.add(miKill);
            }
        } else {
            if (!field.isEnabled()) {
                popPlayer.remove(miKill);
            }
        }

        if (popPlayer.getComponentIndex(menuPlanB) != -1) {
            popPlayer.remove(menuPlanB);
        }
        menuPlanB = new JMenu();
        menuPlanB.setText("Plan 'B': Switch " + field.getText() + " with...");

        if (popPlayer.getComponentIndex(miTop) == -1) {
            miTop = new JMenuItem();
            miTop.setText("Send to top");
            miTop.addActionListener(new java.awt.event.ActionListener() {

                @Override
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    miTopActionPerformed(evt);
                }
            });
            if (field.isEnabled()) {
                popPlayer.add(miTop);
            }
        }

        if (popPlayer.getComponentIndex(miBottom) == -1) {
            miBottom = new JMenuItem();
            miBottom.setText("Send to bottom");
            miBottom.addActionListener(new java.awt.event.ActionListener() {

                @Override
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    miBottomActionPerformed(evt);
                }
            });
            if (field.isEnabled()) {
                popPlayer.add(miBottom);
            }
        }

        if (!field.equals(txtName1) && txtName1.isEnabled()) {
            if (txtName1.isEnabled() && !txtName1.getText().isEmpty()) {
                miP1.setText("#1: " + txtName1.getText());
                miP1.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name1" + from + ", " + to);
                        driver.planB(from, to);
                        update();
                        updateInitLabels();
                    }
                });
                menuPlanB.add(miP1);
            }
        }

        if (!field.equals(txtName2) && txtName2.isEnabled()) {
            if (txtName2.isEnabled() && !txtName2.getText().isEmpty()) {
                miP2.setText("#2: " + txtName2.getText());
                miP2.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name2" + from + ", " + to);
                        driver.planB(from, to + 1);
                        update();
                        updateInitLabels();
                    }
                });

                menuPlanB.add(miP2);
            }
        }
        if (!field.equals(txtName3) && txtName3.isEnabled()) {
            if (txtName3.isEnabled() && !txtName3.getText().isEmpty()) {
                miP3.setText("#3: " + txtName3.getText());
                miP3.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name3" + from + ", " + to);
                        driver.planB(from, to + 2);
                        update();
                        updateInitLabels();
                    }
                });
                menuPlanB.add(miP3);
            }
        }
        if (!field.equals(txtName4) && txtName4.isEnabled()) {
            if (txtName4.isEnabled() && !txtName4.getText().isEmpty()) {
                miP4.setText("#4: " + txtName4.getText());
                miP4.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name4" + from + ", " + to);
                        driver.planB(from, to + 3);
                        update();
                        updateInitLabels();
                    }
                });
                menuPlanB.add(miP4);
            }
        }
        if (!field.equals(txtName5) && txtName5.isEnabled()) {
            if (txtName5.isEnabled() && !txtName5.getText().isEmpty()) {
                miP5.setText("#5: " + txtName5.getText());
                miP5.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name5" + from + ", " + to);
                        driver.planB(from, to + 4);
                        update();
                        updateInitLabels();
                    }
                });
                menuPlanB.add(miP5);
            }
        }
        if (!field.equals(txtName6) && txtName6.isEnabled()) {
            if (txtName6.isEnabled() && !txtName6.getText().isEmpty()) {
                miP6.setText("#6: " + txtName6.getText());
                miP6.addActionListener(new java.awt.event.ActionListener() {

                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        System.out.println("Name6" + from + ", " + to);
                        driver.planB(from, to + 5);
                        update();
                        updateInitLabels();
                    }
                });
                menuPlanB.add(miP6);
            }
        }
        popPlayer.add(menuPlanB);

    }

    private void showDiag(String msg) {
        JOptionPane.showMessageDialog(this, msg);
    }

    private int confirmDiag(String title, String msg) {
        return JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
    }

    private void setEditable(JTextField field) {
        editting = true;
        field.setEditable(true);
        field.requestFocus();
        field.selectAll();

        updateInitLabels();
        //dealt = false;
    }

    private void setNonEditable(JTextField field) {
        field.setEditable(false);
        if (!field.getText().isEmpty()) {
            field.setComponentPopupMenu(popPlayer);
        } else {
            field.setComponentPopupMenu(null);
        }
        if (!newGame) {
            if (!driver.renamePlayer(field.getBackground(), field.getText())) {
                driver.addPlayer(field.getText(), field.getBackground());
            }
        }

        updateInitLabels();
        editting = false;
    }

    public void updateInitLabels() {
        int init = 1;
        if (txtName1.getText().isEmpty()) {
            if (!newGame) {
                lblInit1.setVisible(false);
                lblInit1.setText(null);
            } else {
                lblInit1.setVisible(true);
                lblInit1.setText(null);
            }
        } else {
            lblInit1.setText(init + ": ");
            init++;
            lblInit1.setVisible(true);
        }

        if (txtName2.getText().isEmpty()) {
            if (!newGame) {
                lblInit2.setVisible(false);
                lblInit2.setText(null);
            } else {
                lblInit2.setVisible(true);
                lblInit2.setText(null);
            }
        } else {
            lblInit2.setText(init + ": ");
            init++;
            lblInit2.setVisible(true);
        }

        if (txtName3.getText().isEmpty()) {
            if (!newGame) {
                lblInit3.setVisible(false);
                lblInit3.setText(null);
            } else {
                lblInit3.setVisible(true);
                lblInit3.setText(null);
            }
        } else {
            lblInit3.setText(init + ": ");
            init++;
            lblInit3.setVisible(true);
        }

        if (txtName4.getText().isEmpty()) {
            if (!newGame) {
                lblInit4.setVisible(false);
                lblInit4.setText(null);
            } else {
                lblInit4.setVisible(true);
                lblInit4.setText(null);
            }
        } else {
            lblInit4.setText(init + ": ");
            init++;
            lblInit4.setVisible(true);
        }

        if (txtName5.getText().isEmpty()) {
            if (!newGame) {
                lblInit5.setVisible(false);
                lblInit5.setText(null);
            } else {
                lblInit5.setVisible(true);
                lblInit5.setText(null);
            }
        } else {
            lblInit5.setText(init + ": ");
            init++;
            lblInit5.setVisible(true);
        }

        if (txtName6.getText().isEmpty()) {
            if (!newGame) {
                lblInit6.setVisible(false);
                lblInit6.setText(null);
            } else {
                lblInit6.setVisible(true);
                lblInit6.setText("");
            }
        } else {
            lblInit6.setText(init + ": ");
            init++;
            lblInit6.setVisible(true);
        }
    }

    private void swap(JTextField one, JTextField two) {
        Color col = one.getBackground();
        String name = one.getText();
        one.setBackground(two.getBackground());
        one.setText(two.getText());
        two.setBackground(col);
        two.setText(name);
        System.out.println("switched fields: " + one.getText() + ", " + two.getText());
        update();
    }

    private void deal() {
        try {
            System.out.println(newGame);
            if (newGame) { // new game/new players
                setupGame();
            }
            // get new positions
            counter++;
            animator.run();

        } catch (Exception e) {
            e.printStackTrace();
            //showDiag(e.getMessage());
            // do nothing - they were trying to deal with no names
        }
    }

    private void setupGame() throws Exception {
        driver.newGame();
        createDeck();
        counter = 0;
        animator = new DealAnimationThread(this);
        newGame = false;
        update();
        updateInitLabels();
    }

    private void createDeck() throws Exception {
        ArrayList<Player> players = new ArrayList<Player>();

        if (!txtName1.getText().isEmpty()) {
            Player p = new Player(txtName1.getText(), txtName1.getBackground());
            if (!txtName1.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (!txtName2.getText().isEmpty()) {
            Player p = new Player(txtName2.getText(), txtName2.getBackground());
            if (!txtName2.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (!txtName3.getText().isEmpty()) {
            Player p = new Player(txtName3.getText(), txtName3.getBackground());
            if (!txtName3.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (!txtName4.getText().isEmpty()) {
            Player p = new Player(txtName4.getText(), txtName4.getBackground());
            if (!txtName4.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (!txtName5.getText().isEmpty()) {
            Player p = new Player(txtName5.getText(), txtName5.getBackground());
            if (!txtName5.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (!txtName6.getText().isEmpty()) {
            Player p = new Player(txtName6.getText(), txtName6.getBackground());
            if (!txtName6.isEnabled()) {
                p.die();
            }
            players.add(p);
        }

        if (players.size() >= 3) {
            // null textboxes so only filled ones show up (on update)
            txtName1.setText(null);
            txtName2.setText(null);
            txtName3.setText(null);
            txtName4.setText(null);
            txtName5.setText(null);
            txtName6.setText(null);

            players.trimToSize();
            setDeck(players);
        } else {
            throw new Exception("Not enough players! Games are between 3-6 players.");
        }
    }

    private void killPlayer(int i) {
        driver.killPlayer(i);
        update();
    }

    /**
     * Set the deck with new list of players
     * @param p players
     */
    public void setDeck(ArrayList<Player> p) {
        System.out.println("New deck set");
        driver.setDeck(p);
    }

    /**
     * Refreshes numbers/names/etc for all players with current ArrayList of players
     */
    public void update() {
        ArrayList<Player> players = driver.getList();
        if (players.size() > 5) { // 6 players
            txtName6.setText(players.get(5).getName());
            txtName6.setBackground(players.get(5).getColor());
            txtName6.setEnabled(!players.get(5).isDead());
            txtName6.setVisible(true);
        } else {
            txtName6.setVisible(false);
            txtName6.setText(null);
        }

        if (players.size() > 4) { // 5 players
            txtName5.setText(players.get(4).getName());
            txtName5.setBackground(players.get(4).getColor());
            txtName5.setEnabled(!players.get(4).isDead());
            txtName5.setVisible(true);
        } else {
            txtName5.setVisible(false);
            txtName5.setText(null);
        }

        if (players.size() > 3) { // 4 players
            txtName4.setText(players.get(3).getName());
            txtName4.setBackground(players.get(3).getColor());
            txtName4.setEnabled(!players.get(3).isDead());
            txtName4.setVisible(true);
        } else {
            txtName4.setVisible(false);
            txtName4.setText(null);
        }

        if (players.size() > 2) {
            txtName3.setText(players.get(2).getName());
            txtName3.setBackground(players.get(2).getColor());
            txtName3.setEnabled(!players.get(2).isDead());
            txtName3.setVisible(true);
        } else {
            txtName3.setVisible(false);
            txtName3.setText(null);
        }

        if (players.size() > 1) {
            txtName2.setText(players.get(1).getName());
            txtName2.setBackground(players.get(1).getColor());
            txtName2.setEnabled(!players.get(1).isDead());
            txtName2.setVisible(true);
        } else {
            txtName2.setVisible(false);
            txtName2.setText(null);
        }

        if (players.size() > 0) {
            txtName1.setText(players.get(0).getName());
            txtName1.setBackground(players.get(0).getColor());
            txtName1.setEnabled(!players.get(0).isDead());
            txtName1.setVisible(true);
        } else {
            txtName1.setVisible(false);
            txtName1.setText(null);
        }

        this.setTitle("Encounter # " + driver.getEncounters() + ", Initiative # " + counter);
    }

    // keep names just re-enable players and reset steps
    private void restart() {
        String title = "Confirm Restart Game";
        String msg = "This will reset the initiative counter and restart the game. \nAre you sure?";
        
        if (confirmDiag(title, msg) == JOptionPane.OK_OPTION) {
            newGame = true;
            driver.newStepper();
            driver.setDeals(0);
            this.setTitle(null);
            
            txtName1.setEnabled(true);
            txtName2.setEnabled(true);
            txtName3.setEnabled(true);
            txtName4.setEnabled(true);
            txtName5.setEnabled(true);
            txtName6.setEnabled(true);

            updateInitLabels();
            update();
            updateSteps();
            setFont();
        }
    }

    // clear names and start NEW game
    private void clear(String title, String msg) {
        if (confirmDiag(title, msg) == JOptionPane.OK_OPTION) {
            newGame = true;
            driver.newGame();
            this.setTitle(null);

            txtName1.setText(null);
            txtName1.setEnabled(true);
            txtName1.setBackground(Color.red);
            txtName1.setVisible(true);

            txtName2.setText(null);
            txtName2.setEnabled(true);
            txtName2.setBackground(Color.yellow);
            txtName2.setVisible(true);

            txtName3.setText(null);
            txtName3.setEnabled(true);
            txtName3.setBackground(Color.blue);
            txtName3.setVisible(true);

            txtName4.setText(null);
            txtName4.setEnabled(true);
            txtName4.setBackground(Color.green);
            txtName4.setVisible(true);

            txtName5.setText(null);
            txtName5.setEnabled(true);
            txtName5.setBackground(Color.magenta);
            txtName5.setVisible(true);

            txtName6.setText(null);
            txtName6.setEnabled(true);
            txtName6.setBackground(Color.orange);
            txtName6.setVisible(true);

            updateSteps();
            setFont();
        }
    }

    private void addPlayer() {
        JTextField field = new JTextField();
        
        if (!txtName1.isVisible()) {
            field = txtName1;
        } else if (!txtName2.isVisible()) {
            field = txtName2;
        } else if (!txtName3.isVisible()) {
            field = txtName3;
        } else if (!txtName4.isVisible()) {
            field = txtName4;
        } else if (!txtName5.isVisible()) {
            field = txtName5;
        } else if (!txtName6.isVisible()) {
            field = txtName6;
        } else {
            showDiag("Can only add up to 6 players");
            field = null;
        }

        if (field != null) {
            // skip txtName1, use whatever color it has currently

            if (field == txtName2) {
                // if current color is used for any other textbox, search for a color from list
                if (field.getBackground() == txtName1.getBackground()) {
                    for (Color col : colors) {
                        if (col != txtName1.getBackground()) {
                            field.setBackground(col);
                            break;
                        }
                    }
                }
            } else if (field == txtName3) {
                // if current color is used for any other textbox, search for a color from list
                if (field.getBackground() == txtName1.getBackground() ||
                    field.getBackground() == txtName2.getBackground())
                {
                    for (Color col : colors) {
                        if (col != txtName1.getBackground() &&
                            col != txtName2.getBackground())
                        {
                            field.setBackground(col);
                            break;
                        }
                    }
                }
            } else if (field == txtName4) {
                // if current color is used for any other textbox, search for a color from list
                if (field.getBackground() == txtName1.getBackground() ||
                    field.getBackground() == txtName2.getBackground() ||
                    field.getBackground() == txtName3.getBackground())
                {
                    for (Color col : colors) {
                        if (col != txtName1.getBackground() &&
                            col != txtName2.getBackground() &&
                            col != txtName3.getBackground())
                        {
                            field.setBackground(col);
                            break;
                        }
                    }
                }
            } else if (field == txtName5) {
                // if current color is used for any other textbox, search for a color from list
                if (field.getBackground() == txtName1.getBackground() ||
                    field.getBackground() == txtName2.getBackground() ||
                    field.getBackground() == txtName3.getBackground() ||
                    field.getBackground() == txtName4.getBackground())
                {
                    for (Color col : colors) {
                        if (col != txtName1.getBackground() &&
                            col != txtName2.getBackground() &&
                            col != txtName3.getBackground() &&
                            col != txtName4.getBackground())
                        {
                            field.setBackground(col);
                            break;
                        }
                    }
                }
            } else if (field == txtName6) {
                // if current color is used for any other textbox, search for a color from list
                if (field.getBackground() == txtName1.getBackground() ||
                    field.getBackground() == txtName2.getBackground() ||
                    field.getBackground() == txtName3.getBackground() ||
                    field.getBackground() == txtName4.getBackground() ||
                    field.getBackground() == txtName5.getBackground())
                {
                    for (Color col : colors) {
                        if (col != txtName1.getBackground() &&
                            col != txtName2.getBackground() &&
                            col != txtName3.getBackground() &&
                            col != txtName4.getBackground() &&
                            col != txtName5.getBackground())
                        {
                            field.setBackground(col);
                            break;
                        }
                    }
                }
            }

            field.setVisible(true);
            setEditable(field);

            updateInitLabels();
            setFont();
        }
    }

    private void removePlayer(JTextField field) {
        driver.removePlayer(field.getBackground());
    }

    public void setFont() {
        System.out.println("resizing font ... ");

        float size = txtName1.getHeight() / 2;

        Font font = txtName1.getFont().deriveFont((txtName1.getFont().getStyle() & ~java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, size);
        
        // initiative labels
        lblInit1.setFont(font);
        lblInit2.setFont(font);
        lblInit3.setFont(font);
        lblInit4.setFont(font);
        lblInit5.setFont(font);
        lblInit6.setFont(font);

        txtName1.setFont(font);
        txtName2.setFont(font);
        txtName3.setFont(font);
        txtName4.setFont(font);
        txtName5.setFont(font);
        txtName6.setFont(font);

        pnlMain.revalidate();
        pnlMain.repaint();

        System.out.println("sized to: " + size);
    }

    private void moveToTop(int i) {
        driver.moveToFirst(i);
    }

    private void moveToBottom(int i) {
        driver.moveToLast(i);
    }

    /**
     * Sets the cursor to waiting
     */
    @SuppressWarnings("deprecation")
    public void waitCursor() {
        this.setCursor(Cursor.WAIT_CURSOR);
    }

    /**
     * Sets the cursor back to default
     */
    @SuppressWarnings("deprecation")
    public void doneCursor() {
        this.setCursor(Cursor.DEFAULT_CURSOR);
    }

    private void nextStep() {
        Step s; // current (after advance)
        
        try {
            if (newGame) {
                setupGame();
            } 

            s = driver.nextStep();

            // update steps
            updateSteps();

            if (s.getName().equals(Stepper.ENC_INIT)) {
                driver.setDeals(0);
            }

            if (s.getName().equals(Stepper.ROU_INIT) ||
                s.getName().equals(Stepper.ENC_INIT))
            {
                deal();
            }
            
        } catch (Exception ex) {
            ex.printStackTrace();
            //showDiag(ex.getMessage());
        }
    }

    private void backStep() {
        
        try {
            driver.backStep();

            update();
            updateSteps();

        } catch (Exception ex) {
            ex.printStackTrace();
            //showDiag(ex.getMessage());
        }
    }

    private void monsterDies() {
        try {
            driver.monsterDies();
            updateSteps();
            btnMonsterKilled.setEnabled(false);
            miMonsterKilled.setEnabled(false);
            btnNextStep.requestFocus();

        } catch (Exception ex) {
            ex.printStackTrace();
            //showDiag(ex.getMessage());
        }
    }

    /**
     * Returns driver instance
     * @return driver
     */
    public Main getDriver() {
        return driver;
    }
}
